package org.chinaunicom.permission.dao.impl;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.log4j.Logger;
import org.chinaunicom.permission.dao.BaseDao;
import org.chinaunicom.permission.entity.Menu;
import org.chinaunicom.permission.entity.Role;
import org.chinaunicom.permission.entity.RoleMenu;
import org.chinaunicom.permission.entity.User;
import org.chinaunicom.permission.entity.UserRole;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.PreparedStatementCreator;
import org.springframework.jdbc.core.RowCallbackHandler;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.KeyHolder;

public class BaseDaoImpl<T> implements BaseDao<T> {

	private Logger logger = Logger.getLogger(BaseDaoImpl.class);

	@Autowired
	protected JdbcTemplate jdbcTemplate;

	protected final Class<T> clazz;

	@SuppressWarnings("unchecked")
	protected BaseDaoImpl() {
		clazz = (Class<T>) ((ParameterizedType) getClass()
				.getGenericSuperclass()).getActualTypeArguments()[0];
	}

	@Override
	public void createEntity(T t) {
		KeyHolder keyHolder = new GeneratedKeyHolder();
		if (clazz.getName().equals("org.chinaunicom.permission.entity.Menu")) {
			final Menu Menu = (Menu) t;
			final String sql = "insert into menu(parent_menu_mid, menu_name, menu_url) values(?,?,?)";
			jdbcTemplate.update(new PreparedStatementCreator() {

				@Override
				public PreparedStatement createPreparedStatement(Connection con)
						throws SQLException {
					PreparedStatement ps = con.prepareStatement(sql,
							PreparedStatement.RETURN_GENERATED_KEYS);
					ps.setInt(1, Menu.getParent_menu_mid());
					ps.setString(2, Menu.getMenu_name());
					ps.setString(3, Menu.getMenu_url());
					return ps;
				}
			}, keyHolder);
			Menu.setMid(keyHolder.getKey().intValue());
		}
		if (clazz.getName().equals("org.chinaunicom.permission.entity.Role")) {
			final Role role = (Role) t;
			final String sql = "insert into role(role_name, role_desc) values(?,?)";
			jdbcTemplate.update(new PreparedStatementCreator() {

				@Override
				public PreparedStatement createPreparedStatement(Connection con)
						throws SQLException {
					PreparedStatement ps = con.prepareStatement(sql,
							PreparedStatement.RETURN_GENERATED_KEYS);
					ps.setString(1, role.getRole_name());
					ps.setString(2, role.getRole_desc());
					return ps;
				}
			}, keyHolder);
			role.setRid(keyHolder.getKey().intValue());
		}
		if (clazz.getName().equals("org.chinaunicom.permission.entity.User")) {
			final User user = (User) t;
			final String sql = "insert into user(username,password) values(?,?)";
			jdbcTemplate.update(new PreparedStatementCreator() {

				@Override
				public PreparedStatement createPreparedStatement(Connection con)
						throws SQLException {
					PreparedStatement ps = con.prepareStatement(sql,
							PreparedStatement.RETURN_GENERATED_KEYS);
					ps.setString(1, user.getUsername());
					ps.setString(2, user.getPassword());
					return ps;
				}
			}, keyHolder);
			user.setUid(keyHolder.getKey().intValue());
		}
		if (clazz.getName().equals("org.chinaunicom.permission.entity.UserRole")) {
			final UserRole userRole = (UserRole) t;
			final String sql = "insert into user_role(uid, rid) values(?,?)";
			jdbcTemplate.update(new PreparedStatementCreator() {

				@Override
				public PreparedStatement createPreparedStatement(Connection con)
						throws SQLException {
					PreparedStatement ps = con.prepareStatement(sql,
							PreparedStatement.RETURN_GENERATED_KEYS);
					ps.setInt(1, userRole.getUid());
					ps.setInt(2, userRole.getRid());
					return ps;
				}
			}, keyHolder);
			userRole.setUrid(keyHolder.getKey().intValue());
		}
		if (clazz.getName().equals("org.chinaunicom.permission.entity.RoleMenu")) {
			final RoleMenu roleMenu = (RoleMenu) t;
			final String sql = "insert into role_menu(rid, mid) values(?,?)";
			jdbcTemplate.update(new PreparedStatementCreator() {

				@Override
				public PreparedStatement createPreparedStatement(Connection con)
						throws SQLException {
					PreparedStatement ps = con.prepareStatement(sql,
							PreparedStatement.RETURN_GENERATED_KEYS);
					ps.setInt(1, roleMenu.getRid());
					ps.setInt(2, roleMenu.getMid());
					return ps;
				}
			}, keyHolder);
			roleMenu.setRmid(keyHolder.getKey().intValue());
		}

		logger.debug("插入【" + clazz.getName() + "】对象：主键ID为"
				+ keyHolder.getKey().intValue() + "!");
	}

	@Override
	public void updateEntity(T t) {
		if (clazz.getName().equals("org.chinaunicom.permission.entity.Menu")) {
			Menu menu = (Menu) t;
			String sqlText = "update menu set ";
			Map<String, Object> map = getWillBeChangedField(t);
			Set<String> set = new HashSet<String>();
			set = map.keySet();
			for (String key : set) {
				sqlText += key + "=\"" + map.get(key) + "\",";
			}
			sqlText = sqlText.substring(0, sqlText.length() - 1);
			sqlText += "where mid=\"" + menu.getMid() + "\"";
			jdbcTemplate.update(sqlText);
		}
		if (clazz.getName().equals("org.chinaunicom.permission.entity.Role")) {
			Role role = (Role) t;
			String sqlText = "update role set ";
			Map<String, Object> map = getWillBeChangedField(t);
			Set<String> set = new HashSet<String>();
			set = map.keySet();
			for (String key : set) {
				sqlText += key + "=\"" + map.get(key) + "\",";
			}
			sqlText = sqlText.substring(0, sqlText.length() - 1);
			sqlText += "where rid=\"" + role.getRid() + "\"";
			jdbcTemplate.update(sqlText);
		}
		if (clazz.getName().equals("org.chinaunicom.permission.entity.User")) {
			User user = (User) t;
			String sqlText = "update user set ";
			Map<String, Object> map = getWillBeChangedField(t);
			Set<String> set = new HashSet<String>();
			set = map.keySet();
			for (String key : set) {
				sqlText += key + "=\"" + map.get(key) + "\",";
			}
			sqlText = sqlText.substring(0, sqlText.length() - 1);
			sqlText += "where uid=\"" + user.getUid() + "\"";
			jdbcTemplate.update(sqlText);
		}
		if (clazz.getName().equals("org.chinaunicom.permission.entity.UserRole")) {
			UserRole userRole = (UserRole) t;
			String sqlText = "update user_role set ";
			Map<String, Object> map = getWillBeChangedField(t);
			Set<String> set = new HashSet<String>();
			set = map.keySet();
			for (String key : set) {
				sqlText += key + "=\"" + map.get(key) + "\",";
			}
			sqlText = sqlText.substring(0, sqlText.length() - 1);
			sqlText += "where urid=\"" + userRole.getUrid() + "\"";
			jdbcTemplate.update(sqlText);
		}
		if (clazz.getName().equals("org.chinaunicom.permission.entity.RoleMenu")) {
			RoleMenu roleMenu = (RoleMenu) t;
			String sqlText = "update role_menu set ";
			Map<String, Object> map = getWillBeChangedField(t);
			Set<String> set = new HashSet<String>();
			set = map.keySet();
			for (String key : set) {
				sqlText += key + "=\"" + map.get(key) + "\",";
			}
			sqlText = sqlText.substring(0, sqlText.length() - 1);
			sqlText += "where rmid=\"" + roleMenu.getRmid() + "\"";
			jdbcTemplate.update(sqlText);
		}
		logger.debug("修改【" + clazz.getName() + "】对象!");
	}

	@Override
	public void deleteEntity(T t) {
		if (clazz.getName().equals("org.chinaunicom.permission.entity.User")) {
			User user = (User) t;
			String sqlText = "delete from user ";
			sqlText += "where uid=\"" + user.getUid() + "\"";
			jdbcTemplate.update(sqlText);
		}
		if (clazz.getName().equals("org.chinaunicom.permission.entity.Role")) {
			Role role = (Role) t;
			String sqlText = "delete from role ";
			sqlText += "where rid=\"" + role.getRid() + "\"";
			jdbcTemplate.update(sqlText);
		}
		if (clazz.getName().equals("org.chinaunicom.permission.entity.Menu")) {
			Menu menu = (Menu) t;
			String sqlText = "delete from menu ";
			sqlText += "where mid=\"" + menu.getMid() + "\"";
			jdbcTemplate.update(sqlText);
		}
		if (clazz.getName().equals("org.chinaunicom.permission.entity.UserRole")) {
			UserRole userRole = (UserRole) t;
			String sqlText = "delete from user_role ";
			sqlText += "where urid=\"" + userRole.getUrid() + "\"";
			jdbcTemplate.update(sqlText);
		}
		if (clazz.getName().equals("org.chinaunicom.permission.entity.RoleMenu")) {
			RoleMenu roleMenu = (RoleMenu) t;
			String sqlText = "delete from role_menu ";
			sqlText += "where rmid=\"" + roleMenu.getRmid() + "\"";
			jdbcTemplate.update(sqlText);
		}
		logger.debug("删除【" + clazz.getName() + "】对象!");
	}

	@SuppressWarnings("unchecked")
	@Override
	public T queryEntityById(int id) {
		T t = null;
		if (clazz.getName().equals("org.chinaunicom.permission.entity.Menu")) {
			String sql = "select * from menu where mid=?";
			final Menu menu = new Menu();
			jdbcTemplate.query(sql, new Object[] { id },
					new RowCallbackHandler() {

						@Override
						public void processRow(ResultSet rs)
								throws SQLException {
							menu.setMid(rs.getInt("mid"));
							menu.setParent_menu_mid(rs.getInt("parent_menu_mid"));
							menu.setMenu_name(rs.getString("menu_name"));
							menu.setMenu_url(rs.getString("menu_url"));
						}
					});
			t = (T) menu;
		}
		if (clazz.getName().equals("org.chinaunicom.permission.entity.Role")) {
			String sql = "select * from role where rid=?";
			final Role role = new Role();
			jdbcTemplate.query(sql, new Object[] { id },
					new RowCallbackHandler() {

						@Override
						public void processRow(ResultSet rs)
								throws SQLException {
							role.setRid(rs.getInt("rid"));
							role.setRole_name(rs.getString("role_name"));
							role.setRole_desc(rs.getString("role_desc"));
						}
					});
			t = (T) role;
		}
		if (clazz.getName().equals("org.chinaunicom.permission.entity.User")) {
			String sql = "select * from user where uid=?";
			final User user = new User();
			jdbcTemplate.query(sql, new Object[] { id },
					new RowCallbackHandler() {

						@Override
						public void processRow(ResultSet rs)
								throws SQLException {
							user.setUid(rs.getInt("uid"));
							user.setUsername(rs.getString("username"));
							user.setPassword(rs.getString("password"));
						}
					});
			t = (T) user;
		}
		if (clazz.getName().equals("org.chinaunicom.permission.entity.UserRole")) {
			String sql = "select * from user_role where urid=?";
			final UserRole userRole = new UserRole();
			jdbcTemplate.query(sql, new Object[] { id },
					new RowCallbackHandler() {

						@Override
						public void processRow(ResultSet rs)
								throws SQLException {
							userRole.setUrid(rs.getInt("urid"));
							userRole.setUid(rs.getInt("uid"));
							userRole.setRid(rs.getInt("rid"));
						}
					});
			t = (T) userRole;
		}
		if (clazz.getName().equals("org.chinaunicom.permission.entity.RoleMenu")) {
			String sql = "select * from role_menu where rmid=?";
			final RoleMenu roleMenu = new RoleMenu();
			jdbcTemplate.query(sql, new Object[] { id },
					new RowCallbackHandler() {

						@Override
						public void processRow(ResultSet rs)
								throws SQLException {
							roleMenu.setRmid(rs.getInt("rmid"));
							roleMenu.setRid(rs.getInt("rid"));
							roleMenu.setMid(rs.getInt("mid"));
						}
					});
			t = (T) roleMenu;
		}
		logger.debug("查询【" + clazz.getName() + "】对象：" + t.toString());
		return t;
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<T> queryEntityList() {
		List<T> list = null;
		if (clazz.getName().equals("org.chinaunicom.permission.entity.Menu")) {
			String sql = "select mid,parent_menu_mid,menu_name,menu_url from menu limit 0,10";
			list = jdbcTemplate.query(sql, new RowMapper<T>(){
				@Override
				public T mapRow(ResultSet rs, int rowNum)
						throws SQLException {
					Menu menu = new Menu();
					menu.setMid(rs.getInt("mid"));
					menu.setParent_menu_mid(rs.getInt("parent_menu_mid"));
					menu.setMenu_name(rs.getString("menu_name"));
					menu.setMenu_url(rs.getString("menu_url"));
					return (T)menu;
				}});
		}
		if (clazz.getName().equals("org.chinaunicom.permission.entity.Role")) {
			String sql = "select rid,role_name,role_desc from role limit 0,10";
			list = jdbcTemplate.query(sql, new RowMapper<T>(){
				@Override
				public T mapRow(ResultSet rs, int rowNum)
						throws SQLException {
					Role role = new Role();
					role.setRid(rs.getInt("rid"));
					role.setRole_name(rs.getString("role_name"));
					role.setRole_desc(rs.getString("role_desc"));
					return (T) role;
				}});
		}
		if (clazz.getName().equals("org.chinaunicom.permission.entity.User")) {
			String sql = "select uid,username,password from user limit 0,10";
			list = jdbcTemplate.query(sql, new RowMapper<T>(){
				@Override
				public T mapRow(ResultSet rs, int rowNum)
						throws SQLException {
					User user = new User();
					user.setUid(rs.getInt("uid"));
					user.setUsername(rs.getString("username"));
					user.setPassword(rs.getString("password"));
					return (T) user;
				}});
		}
		if (clazz.getName().equals("org.chinaunicom.permission.entity.UserRole")) {
			String sql = "select urid,uid,rid from user_role limit 0,10";
			list = jdbcTemplate.query(sql, new RowMapper<T>(){
				@Override
				public T mapRow(ResultSet rs, int rowNum)
						throws SQLException {
					UserRole userRole = new UserRole();
					userRole.setUrid(rs.getInt("urid"));
					userRole.setUid(rs.getInt("uid"));
					userRole.setRid(rs.getInt("rid"));
					return (T) userRole;
				}});
		}
		if (clazz.getName().equals("org.chinaunicom.permission.entity.RoleMenu")) {
			String sql = "select rmid,rid,mid from role_menu limit 0,10";
			list = jdbcTemplate.query(sql, new RowMapper<T>(){
				@Override
				public T mapRow(ResultSet rs, int rowNum)
						throws SQLException {
					RoleMenu roleMenu = new RoleMenu();
					roleMenu.setRid(rs.getInt("rid"));
					roleMenu.setMid(rs.getInt("rid"));
					roleMenu.setRmid(rs.getInt("rmid"));
					return (T) roleMenu;
				}});
		}
		logger.debug("查询【" + clazz.getName() + "】对象列表，共" + list.size() + "个元素！");
		return list;
	}

	public Map<String, Object> getWillBeChangedField(T t) {
		Map<String, Object> map = new HashMap<String, Object>();
		try {
			Field[] fields = this.clazz.getDeclaredFields();
			for (Field field : fields) {
				field.setAccessible(true);
				if (field.get(t) != null) {
					map.put(field.getName(), field.get(t));
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return map;
	}

}